Using Conditional Statements with if, else, and when in Kotlin
Course: Android App Development
Topic: Using Conditional Statements with if, else, and when
Course Link: Android App Development Course
Demo Link: Register for a Course Demo
Official Website: JustAcademy
1. Introduction to Conditional Statements in Kotlin
Conditional statements are programming structures that allow an application to make decisions based on specific conditions. They determine which block of code should execute depending on whether a condition is true or false.
In Kotlin, the primary conditional structures are if, if-else, else if, and when. These structures help developers implement decision-making logic in Android applications.
For example, an Android application may use conditional statements to:
- Check whether a user has entered valid login credentials.
- Display a message depending on a user's age.
- Determine whether a payment was successful.
- Show different messages based on an order's status.
- Enable or disable a button depending on form validation.
- Display different screens or content according to a user's role.
- Assign grades based on examination marks.
Understanding conditional statements is essential for building applications that respond correctly to user actions, input values, and changing application states.
2. Learning Objectives
After completing this topic, learners should be able to:
- Understand the purpose of conditional statements in Kotlin.
- Write conditions using comparison and logical operators.
- Implement simple
if statements.
- Use
if-else to handle two alternative outcomes.
- Apply
else if to check multiple conditions.
- Use nested conditional statements when necessary.
- Understand
if as an expression that returns a value.
- Use
when for multiple branches and alternative conditions.
- Work with ranges, collections, and type checks in
when.
- Apply conditional logic to practical Android development scenarios.
- Identify common conditional statement errors and correct them.
3. Understanding Conditions and Boolean Expressions
A condition is an expression that evaluates to either true or false. Kotlin uses Boolean expressions to decide which conditional branch should execute.
3.1 Example of a Boolean Condition
fun main() {
val age = 22
val isEligible = age >= 18
println(isEligible)
}
Output:
true
In this example, the expression age >= 18 evaluates to true because the value of age is 22.
3.2 Common Comparison Operators
| Operator |
Meaning |
Example |
Result |
== |
Equal to |
10 == 10 |
true |
!= |
Not equal to |
10 != 5 |
true |
> |
Greater than |
10 > 5 |
true |
< |
Less than |
5 < 10 |
true |
>= |
Greater than or equal to |
10 >= 10 |
true |
<= |
Less than or equal to |
5 <= 10 |
true |
3.3 Logical Operators
Logical operators combine or reverse Boolean conditions. They are especially useful when an application must validate several requirements simultaneously.
| Operator |
Meaning |
Example |
&& |
Logical AND: both conditions must be true |
age >= 18 && hasId |
|| |
Logical OR: at least one condition must be true |
isAdmin || isModerator |
! |
Logical NOT: reverses a Boolean value |
!isLoggedIn |
Example: Checking Multiple Conditions
fun main() {
val age = 24
val hasValidId = true
if (age >= 18 && hasValidId) {
println("Requirements satisfied")
}
}
Output:
Requirements satisfied
Both conditions are true, so the code inside the if block executes.
4. Using the if Statement
The if statement executes a block of code when a specified condition evaluates to true. If the condition is false and no alternative branch is provided, the block is skipped.
4.1 Syntax
if (condition) {
// Execute this code when the condition is true
}
4.2 Example: Checking Age
fun main() {
val age = 20
if (age >= 18) {
println("You are eligible to register.")
}
}
Output:
You are eligible to register.
The condition age >= 18 is true, so Kotlin executes the statement inside the block.
4.3 Example: Checking a Product Price
fun main() {
val productPrice = 499.0
if (productPrice > 0) {
println("The product has a valid price.")
}
}
This example checks whether the product price is greater than zero before displaying a message.
4.4 When to Use if
- When checking a single condition.
- When performing an action only if a requirement is satisfied.
- When validating user input.
- When checking whether a value is null.
- When implementing a simple application rule.
5. Using the if-else Statement
The if-else structure provides two possible execution paths. If the condition is true, the if block runs. Otherwise, the else block runs.
5.1 Syntax
if (condition) {
// Code executed when the condition is true
} else {
// Code executed when the condition is false
}
5.2 Example: Pass or Fail
fun main() {
val marks = 72
if (marks >= 40) {
println("Result: Pass")
} else {
println("Result: Fail")
}
}
Output:
Result: Pass
If the marks are below 40, the program displays Result: Fail.
5.3 Example: Login Status
fun main() {
val isLoggedIn = false
if (isLoggedIn) {
println("Welcome to your account.")
} else {
println("Please log in to continue.")
}
}
Output:
Please log in to continue.
This type of conditional logic can help determine which message to show in an application. Actual authentication must also verify credentials securely rather than relying only on a local Boolean value.
5.4 Example: Even or Odd Number
fun main() {
val number = 17
if (number % 2 == 0) {
println("The number is even.")
} else {
println("The number is odd.")
}
}
Output:
The number is odd.
The remainder operator % returns the remainder after division. If a number divided by two has a remainder of zero, it is even.
6. Using else if for Multiple Conditions
The else if structure allows a program to check multiple conditions in sequence. Kotlin evaluates the conditions from top to bottom and executes the first matching branch.
6.1 Syntax
if (condition1) {
// First condition is true
} else if (condition2) {
// Second condition is true
} else if (condition3) {
// Third condition is true
} else {
// No previous condition is true
}
6.2 Example: Assigning Grades
fun main() {
val marks = 86
if (marks >= 90) {
println("Grade A+")
} else if (marks >= 80) {
println("Grade A")
} else if (marks >= 70) {
println("Grade B")
} else if (marks >= 60) {
println("Grade C")
} else if (marks >= 40) {
println("Grade D")
} else {
println("Fail")
}
}
Output:
Grade A
Because 86 is below 90 but greater than or equal to 80, the second branch executes.
6.3 Why Condition Order Matters
When conditions overlap, place more restrictive or higher-priority conditions before broader conditions.
For example, this code contains a logic error:
val marks = 95
if (marks >= 40) {
println("Pass")
} else if (marks >= 90) {
println("Excellent")
}
The second condition will never be reached for marks of 95 because the first condition already matches. A better version is:
val marks = 95
if (marks >= 90) {
println("Excellent")
} else if (marks >= 40) {
println("Pass")
} else {
println("Fail")
}
7. Nested if Statements
A nested if statement is an if statement placed inside another conditional block. It is useful when a second decision should be considered only after an initial condition is satisfied.
7.1 Example: Course Enrollment
fun main() {
val age = 22
val hasCompletedPrerequisites = true
if (age >= 18) {
if (hasCompletedPrerequisites) {
println("Enrollment approved.")
} else {
println("Complete the prerequisites first.")
}
} else {
println("You must be at least 18 years old.")
}
}
Output:
Enrollment approved.
The program first checks the age requirement and then checks prerequisite completion.
7.2 Advantages and Limitations
- Nested conditions can represent dependent decisions.
- They can make multi-step validation explicit.
- Too many nested blocks can reduce readability.
- Consider using logical operators or a
when expression when the logic becomes difficult to follow.
8. Using if as an Expression
In Kotlin, if can be used as an expression that returns a value. This allows a conditional result to be assigned directly to a variable. Unlike languages that use a separate ternary operator, Kotlin can express the same choice using if-else.
8.1 Syntax
val result = if (condition) {
valueIfTrue
} else {
valueIfFalse
}
8.2 Example: Finding the Larger Number
fun main() {
val firstNumber = 25
val secondNumber = 40
val largerNumber = if (firstNumber > secondNumber) {
firstNumber
} else {
secondNumber
}
println("Larger number: $largerNumber")
}
Output:
Larger number: 40
8.3 Example: Calculating a Discount
fun main() {
val purchaseAmount = 2500.0
val discountRate = if (purchaseAmount >= 2000.0) {
0.10
} else {
0.05
}
val discount = purchaseAmount * discountRate
val finalAmount = purchaseAmount - discount
println("Discount: $discount")
println("Final amount: $finalAmount")
}
Output:
Discount: 250.0
Final amount: 2250.0
When if is used as an expression, both branches must provide a suitable value. This makes it possible for Kotlin to determine the type of the result.
9. Introduction to the when Expression
The when expression is Kotlin's flexible structure for checking multiple possible values or conditions. It serves a role similar to the switch statement in several other programming languages, but it supports additional features such as ranges, type checks, and condition-based branches.
Use when when you have several possible outcomes and want the logic to remain readable.
9.1 Basic Syntax
when (value) {
option1 -> {
// Execute code for option1
}
option2 -> {
// Execute code for option2
}
else -> {
// Execute if no branch matches
}
}
9.2 Example: Selecting a Day
fun main() {
val dayNumber = 3
when (dayNumber) {
1 -> println("Monday")
2 -> println("Tuesday")
3 -> println("Wednesday")
4 -> println("Thursday")
5 -> println("Friday")
6 -> println("Saturday")
7 -> println("Sunday")
else -> println("Invalid day number")
}
}
Output:
Wednesday
Kotlin checks each branch in order. When a matching branch is found, its code executes. Unlike traditional fall-through behavior in some switch statements, Kotlin does not automatically continue into the next branch.
10. Understanding the else Branch in when
The else branch handles values that do not match any of the preceding branches. It is commonly used as a default or fallback outcome.
Example: Order Status
fun main() {
val orderStatus = "Processing"
when (orderStatus) {
"Pending" -> println("Your order is awaiting confirmation.")
"Processing" -> println("Your order is being prepared.")
"Shipped" -> println("Your order is on its way.")
"Delivered" -> println("Your order has been delivered.")
else -> println("Unknown order status.")
}
}
Output:
Your order is being prepared.
When no branch matches, the else branch provides a predictable fallback.
Important: A when used as an expression must cover all possible cases. An else branch is often the simplest way to do this. However, it may be omitted when the compiler can establish that all cases of a suitable type, such as an enum or sealed hierarchy, have been covered. A when used only as a statement does not always require every case to be covered.
11. Using when as an Expression
A when expression returns the value of the first matching branch. Its result can be stored in a variable, returned from a function, or used in another expression.
Example: Converting a Menu Choice into a Message
fun main() {
val menuChoice = 2
val message = when (menuChoice) {
1 -> "Open Profile"
2 -> "Open Settings"
3 -> "Open Help"
else -> "Invalid menu choice"
}
println(message)
}
Output:
Open Settings
Example: Determining a Shipping Fee
fun main() {
val deliveryType = "Express"
val shippingFee = when (deliveryType) {
"Standard" -> 50
"Express" -> 100
"SameDay" -> 150
else -> 0
}
println("Shipping fee: $shippingFee")
}
Output:
Shipping fee: 100
This approach avoids declaring a variable first and then assigning it separately in each branch.
12. Using when Without a Subject
A when expression does not always need a value in parentheses. Without a subject, each branch contains a Boolean condition. Kotlin evaluates these conditions in order and executes the first branch whose condition is true.
Example: Classifying a Number
fun main() {
val number = -5
val result = when {
number > 0 -> "Positive number"
number < 0 -> "Negative number"
else -> "Zero"
}
println(result)
}
Output:
Negative number
Example: Checking Login Requirements
fun main() {
val userName = "student"
val passwordLength = 10
val accountEnabled = true
val message = when {
userName.isBlank() -> "Enter a username."
passwordLength < 8 -> "Password is too short."
!accountEnabled -> "Account is disabled."
else -> "Input checks passed."
}
println(message)
}
Output:
Input checks passed.
This example illustrates local validation logic only. Real authentication requires secure password handling and server-side verification where appropriate.
13. Combining Multiple Values in a when Branch
Kotlin allows multiple values to share the same branch by separating them with commas. This reduces repeated code when several inputs should produce the same result.
Example: Weekday and Weekend Classification
fun main() {
val day = 6
when (day) {
1, 2, 3, 4, 5 -> println("Weekday")
6, 7 -> println("Weekend")
else -> println("Invalid day")
}
}
Output:
Weekend
Example: Supported User Roles
fun main() {
val role = "Editor"
when (role) {
"Admin", "Manager" -> println("Administrative access category")
"Editor", "Author" -> println("Content management category")
"Viewer" -> println("Read-only category")
else -> println("Unknown role")
}
}
When implementing real permissions, each role must be checked against an explicit and secure authorization policy. Displaying a role-specific message alone does not enforce access control.
14. Using Ranges in when
Kotlin supports range checks with the in operator. This is useful for grouping numerical values into categories such as grade ranges, age groups, or performance levels.
Example: Assigning Grades with Ranges
fun main() {
val marks = 78
val grade = when (marks) {
in 90..100 -> "A"
in 80..89 -> "B"
in 70..79 -> "C"
in 60..69 -> "D"
in 40..59 -> "E"
in 0..39 -> "F"
else -> "Invalid marks"
}
println("Grade: $grade")
}
Output:
Grade: C
The range 70..79 includes both 70 and 79. The final else branch handles marks outside the expected range.
Example: Checking Membership in a Collection
fun main() {
val selectedCode = 20
val validCodes = setOf(10, 20, 30)
when (selectedCode) {
in validCodes -> println("Valid code")
else -> println("Invalid code")
}
}
This technique is useful when several allowed values are stored in a collection.
15. Using Type Checks in when
The when expression can check the type of a value using is and !is. This is helpful when a function accepts a general type but needs to respond differently to different actual types.
Example: Handling Different Data Types
fun describeValue(value: Any): String {
return when (value) {
is String -> "Text with ${value.length} characters"
is Int -> "Integer value: $value"
is Double -> "Decimal value: $value"
is Boolean -> "Boolean value: $value"
else -> "Unsupported data type"
}
}
fun main() {
println(describeValue("Kotlin"))
println(describeValue(100))
println(describeValue(19.5))
println(describeValue(true))
}
Output:
Text with 6 characters
Integer value: 100
Decimal value: 19.5
Boolean value: true
After a successful type check, Kotlin can often smart-cast the value to the checked type within that branch. This allows operations such as value.length for a string without an explicit cast.
16. Handling Nullable Values in Conditional Statements
Android applications frequently work with optional input, API responses, and data that may not yet be available. Kotlin's nullable types allow developers to represent these situations explicitly.
Example: Checking a Nullable Name
fun main() {
val userName: String? = null
if (userName != null) {
println("Welcome, $userName")
} else {
println("Guest user")
}
}
Output:
Guest user
Inside the true branch, Kotlin can generally treat a stable local variable as non-null after the null check.
Example: Using a Nullable Boolean
fun main() {
val isNotificationEnabled: Boolean? = null
if (isNotificationEnabled == true) {
println("Notifications are enabled.")
} else {
println("Notifications are not confirmed as enabled.")
}
}
When a Boolean value is nullable, checking explicitly for true or false avoids treating a null value as though it were an ordinary Boolean.
17. Difference Between if-else and when
| Feature |
if-else |
when |
| Best suited for |
Simple decisions and ranges expressed as conditions |
Several possible values or multiple ordered conditions |
| Number of branches |
Usually clear for one or a few alternatives |
Convenient for many alternatives |
| Value matching |
Uses Boolean expressions |
Can match values, ranges, types, and conditions |
| Returns a value |
Yes, when used as an expression with suitable branches |
Yes, when used as an expression with exhaustive branches |
| Default branch |
else |
else, unless all cases are covered |
| Example |
if (age >= 18) "Adult" else "Minor" |
when (status) { "Paid" -> "Complete"; else -> "Pending" } |
Best practice: Use if for straightforward binary conditions. Use when when several alternatives need to be checked. Choose the structure that makes the intended logic easiest to understand.
18. Applying Conditional Statements in Android Apps
Conditional statements are commonly used in Android application logic, including validation, navigation decisions, user-interface state, and responses to service results.
18.1 Example: Form Validation
fun validateUserName(userName: String): String {
return if (userName.isBlank()) {
"Username is required."
} else if (userName.length < 3) {
"Username must contain at least 3 characters."
} else {
"Username looks valid."
}
}
fun main() {
println(validateUserName("Anu"))
println(validateUserName(""))
}
Output:
Username looks valid.
Username is required.
This is a simple validation example. Production applications should also consider allowed characters, server-side validation, accessibility, and appropriate error presentation.
18.2 Example: Payment Status
fun getPaymentMessage(status: String): String {
return when (status) {
"SUCCESS" -> "Payment completed."
"PENDING" -> "Payment is being processed."
"FAILED" -> "Payment could not be completed."
"CANCELLED" -> "Payment was cancelled."
else -> "Payment status is unavailable."
}
}
fun main() {
println(getPaymentMessage("SUCCESS"))
}
Output:
Payment completed.
In a real payment application, payment status should be verified through a trusted payment service rather than inferred solely from a local variable or user input.
18.3 Example: Displaying a Connection Message
fun getConnectionMessage(isConnected: Boolean): String {
return if (isConnected) {
"Connection available."
} else {
"Check your internet connection."
}
}
This function returns a different message based on the Boolean argument. In a real Android application, connection monitoring should use appropriate platform APIs and handle changes over time.
18.4 Example: Handling UI State
enum class ScreenState {
LOADING,
SUCCESS,
EMPTY,
ERROR
}
fun getScreenMessage(state: ScreenState): String {
return when (state) {
ScreenState.LOADING -> "Loading data..."
ScreenState.SUCCESS -> "Data loaded successfully."
ScreenState.EMPTY -> "No data available."
ScreenState.ERROR -> "Unable to load data."
}
}
Using an enum with an exhaustive when expression helps ensure that every declared state has a corresponding message. If a new enum value is added, the compiler can help identify places where the new case must be handled.
19. Common Errors and Troubleshooting
| Problem |
Cause |
Solution |
| Condition does not compile |
The expression does not evaluate to a Boolean value. |
Use a valid Boolean expression such as age >= 18. |
| Incorrect comparison |
Using = instead of == for equality. |
Use == to compare values for equality. |
| Wrong branch executes |
Conditions overlap or are ordered incorrectly. |
Place more specific conditions before broader conditions. |
| Missing when case |
A when expression does not cover every possible case. |
Add an else branch or cover all cases for the relevant type. |
| Unexpected null value |
A nullable value was assumed to contain a non-null value. |
Use an explicit null check, safe call, or suitable fallback. |
| Too many nested conditions |
Complex logic is difficult to follow. |
Refactor into smaller functions or use a clear when expression. |
| Incorrect grade or range result |
A boundary value was omitted or assigned to the wrong range. |
Test minimum, maximum, and boundary values. |
| Unexpected when result |
An earlier branch matches before the intended branch. |
Review branch order and make conditions mutually appropriate. |
20. Best Practices for Writing Conditional Logic
- Write conditions that are easy to read and understand.
- Use meaningful variable and function names.
- Prefer
if for simple two-way decisions.
- Prefer
when for multiple alternatives.
- Order overlapping conditions carefully.
- Use an appropriate fallback for unexpected values.
- Keep nested conditional blocks as shallow as practical.
- Use nullable types and explicit null checks where needed.
- Use exhaustive
when expressions for enums and sealed types when appropriate.
- Separate complex business rules into small, testable functions.
- Test boundary values, invalid inputs, and unexpected states.
- Do not rely on UI conditions alone to enforce security or authorization.
- Use consistent indentation and braces to improve readability.
21. Practical Project: Student Result Calculator
Objective: Create a Kotlin program that calculates a student's average marks and assigns a result category using if, else if, else, and when.
Project Requirements
- Store a student's name and marks for three subjects.
- Calculate total and average marks.
- Validate that the average falls between 0 and 100.
- Use conditional statements to determine the result category.
- Use a
when expression to display a suitable performance message.
- Display the student's name, total, average, grade, and message.
Sample Solution
fun main() {
val studentName = "Riya"
val subjectOne = 85
val subjectTwo = 78
val subjectThree = 92
val total = subjectOne + subjectTwo + subjectThree
val average = total.toDouble() / 3
if (average !in 0.0..100.0) {
println("Invalid marks.")
return
}
val grade = if (average >= 90) {
"A"
} else if (average >= 80) {
"B"
} else if (average >= 70) {
"C"
} else if (average >= 40) {
"D"
} else {
"F"
}
val performanceMessage = when (grade) {
"A" -> "Excellent performance"
"B" -> "Very good performance"
"C" -> "Good performance"
"D" -> "Passed"
"F" -> "Needs improvement"
else -> "Unknown grade"
}
println("Student: $studentName")
println("Total: $total")
println("Average: $average")
println("Grade: $grade")
println("Result: $performanceMessage")
}
Expected output:
Student: Riya
Total: 255
Average: 85.0
Grade: B
Result: Very good performance
Project Explanation
- The program stores the student's name and three subject marks.
- It calculates the total and converts the total to a decimal value before calculating the average.
- An
if condition checks whether the average is within the permitted range.
- An
if-else if chain assigns the grade based on the average.
- A
when expression maps the grade to a performance message.
- The program displays the final result.
Extension task: Modify the project to validate each subject mark individually, handle missing marks, and display a different message for students who fail any required subject.
22. Additional Practice Exercises
- Write a program that checks whether a number is positive, negative, or zero.
- Use
if-else to determine whether a number is even or odd.
- Write an
else if chain that assigns grades based on marks.
- Use a
when expression to display the name of a month based on its number.
- Use ranges in
when to classify age groups.
- Create a function that returns a message based on a payment status.
- Write a nullable-value example that displays a fallback username.
- Use
when without a subject to identify a number as positive, negative, or zero.
- Create an enum for loading, success, empty, and error states, then handle each state with
when.
- Refactor a deeply nested conditional into smaller functions or a clear
when expression.
23. Interview Questions and Answers
Q1. What are conditional statements in Kotlin?
Conditional statements control program flow by executing different blocks of code depending on whether specified conditions are satisfied.
Q2. What is the purpose of an if statement?
An if statement executes a block when its Boolean condition evaluates to true.
Q3. What is the difference between if and if-else?
An if statement can execute code only when a condition is true. An if-else structure provides an alternative block when the condition is false.
Q4. What is else if used for?
else if allows multiple conditions to be checked sequentially, with the first matching branch being executed.
Q5. What is a nested if statement?
A nested if is a conditional statement placed inside another conditional block, often used for dependent decisions.
Q6. Can if return a value in Kotlin?
Yes. Kotlin supports if expressions, which return the value of the selected branch. An else branch is required when the result is used as an expression.
Q7. What is the when expression?
when is a Kotlin conditional structure that can select a branch based on values, ranges, type checks, or Boolean conditions.
Q8. Is when similar to switch in Java?
Yes, it serves a similar purpose, but Kotlin's when supports more flexible matching and can return a value directly.
Q9. What is the purpose of else in when?
The else branch handles cases that do not match preceding branches. It is often used to make a when expression exhaustive.
Q10. Can when be used without a subject?
Yes. In when without a subject, each branch contains a Boolean condition that is evaluated in order.
Q11. Can multiple values share a when branch?
Yes. Multiple values can be separated by commas, allowing one branch to handle several matching values.
Q12. How can when check a range?
The in operator can test whether a value belongs to a range, such as in 70..79.
Q13. What is the difference between && and ||?
&& requires both conditions to be true, while || requires at least one condition to be true.
Q14. What is smart casting in Kotlin?
Smart casting allows Kotlin to treat a value as a more specific type after a successful type check or suitable null check when the compiler can verify that the value remains stable.
Q15. When should you choose when instead of if-else?
Use when when several possible values or conditions need to be handled clearly. Use if-else for simple binary decisions.
24. Quick Revision Checklist
if executes a block when a condition is true.
if-else provides two alternative execution paths.
else if checks multiple conditions in order.
- Nested conditions support dependent decisions.
- Kotlin allows
if to return a value as an expression.
when handles multiple possible values and conditions.
when can be used with or without a subject.
- Multiple values can share a
when branch using commas.
- Use
in for range and collection membership checks.
- Use
is and !is for type checks.
- Use an
else branch when a fallback is needed.
- Test boundary conditions and unexpected inputs.
- Keep conditional logic readable, maintainable, and secure.
25. Useful Learning Resources
26. Conclusion
Conditional statements are fundamental to Kotlin programming because they allow applications to make decisions and respond to different situations. The if statement is ideal for simple checks, if-else handles alternative outcomes, and else if supports multiple conditions. The when expression provides a clear and flexible way to handle several values, ranges, types, and Boolean conditions.
By practising these structures with real-world examples such as student results, login validation, payment status, and Android screen states, learners can develop reliable decision-making logic. Apply these concepts in small Kotlin programs before integrating them into complete Android applications.